<?php

/**
 * Created by PhpStorm.
 * User: squall
 * Date: 2023/9/11
 * Time:
 */

namespace app;

use app\model\Base;
use plugin\webman\gateway\Events;
use support\Redis;
use Workerman\Timer;

class Task
{
    //status
    const ROBOT_ONLINE = 1; //在线
    const ROBOT_OFFLINE = 0; //离线

    ///usr/local/php/bin/php /www/first/webmanlds/start.php reload  平滑重启会触发
    //onWorkerStart
    public function onWorkerStart()
    {
        // redis没启动会导致频繁重启 redis 1002被占用 需要重建用户组及用户
        //lsb_release -a 查看 ubuntu版本
        // cat /etc/group 查看 redis组 是否创建
        // cat  /etc/passwd 查看 redis用户 是否创建

        $key = "onWorkerStart";
        $last = Base::redisGet($key);
        $now = time();
        $utime = 0;
        if ($last) {

            $utime = $now - $last;
        }

        Base::redisSet($key, $now, 3600 * 24);
        devlog("onWorkerStart usetime {$utime}-----------------------------");

        self::delrobotlist();
        $md = date("md");
        $tokenkey = "schoolwstoken{$md}";
        Redis::del($tokenkey);

        Base::gettoken();


        $this->datainit();

        // 每隔10秒检查一次数据库是否有新用户注册
        Timer::add(5, function () {
            $this->datasync();
            $this->robotdata();
        });
        Timer::add(10, function () {
            $this->studytime();
            $this->checkrobotheartbeat();
        });
        Timer::add(20, function () {

            //刚开机的时候可能还没有IP 所以需要等待几秒
            Base::gettoken();


            $this->datainit();
        });


        Timer::add(60, function () {

            self::robotonline();
        });
        //        Timer::add(120, function () {
        //            $this->checkack();
        //
        //        });
    }

    public static function checkcmd($cmd, $surveillancefd)
    {

        $key = "ackcount:{$cmd}:{$surveillancefd}";

        $count = Base::redisGet($key);

        if ($count) {
            $key = "broadcastsurid:{$cmd}:{$surveillancefd}";
            $sendcount = Base::redisGet($key);
            $sendcount = $sendcount ? $sendcount : 1;
            $rate = ($count / $sendcount) * 100;

            $rate = floor($rate);

            $lost = $sendcount - $count;
            $toastmsg = "send:{$sendcount} ack:{$count} lost:{$lost} rate:{$rate}%";


            $surdata["msg"] = "$toastmsg";
            $surdata["code"] = 0;

            $surdata["data"]["cmd"] = "toast";
            $surdata["data"]["coach_id"] = 0;
            $surdata["data"]["imei"] = "";
            Base::pushJson($surdata, $surveillancefd); //toast
        }
    }

    public function checkack()
    {
        $surveillancelistkey = "surveillancelist";
        $surveillancelist = Base::redisGetArr($surveillancelistkey);
        if ($surveillancelist) {
            foreach ($surveillancelist as $surveillanceinfo) {
                $surveillancefd = $surveillanceinfo["fd"];

                // $cmd = "robotcarsync";
                //   self::checkcmd($cmd, $surveillancefd);
                $cmd = "callin";

                self::checkcmd($cmd, $surveillancefd);
            }
        }
    }

    public function brake()
    {
        /* $brakekey = "brakebyimei:*";
         $brakekeylist = Redis::keys($brakekey);
         if ($brakekeylist) {
             foreach ($brakekeylist as $brakekey) {
                 $brakekey = trim($brakekey, "swoft:");
                 if ($robotfd = Redis::get($brakekey)) {
                     $rdata["code"] = 0;
                     $rdata["msg"] = "brake";
                     $rdata["data"]["cmd"] = "brake";
                     $rtjson = json_encode($rdata);
                     $robotfd = (int)$robotfd;
                     server()->push($robotfd, $rtjson);
                 }
             }
         }*/
    }

    public static function delrobotlist()
    {
        //  devlog("delrobotlist");

        $md = date("md", strtotime("-1 day"));


        $key = "errbyimei:{$md}:*";
        self::clearlistByKeys($key);

        $key = "passidbyimei:*";
        self::clearlistByKeys($key);

        $key = "autocall:*";
        self::clearlistByKeys($key);

        $key = "autocallnum:*";
        self::clearlistByKeys($key);

        $numberofmissedcallskey = "numberofmissedcalls:*";
        self::clearlistByKeys($numberofmissedcallskey);

        $surinfokey = "SurinfoByImei:*";
        self::clearlistByKeys($surinfokey);

        $fdkey = "deviceinfobyfd:*";
        self::clearlistByKeys($fdkey);

        $robotinfokey = "robotinfo:*";
        self::clearlistByKeys($robotinfokey);

        $key = "seterrnumbystudent:{$md}:*";
        self::clearlistByKeys($key);

        //   broadcastsurid
        $key = "broadcastsurid:*";
        self::clearlistByKeys($key);

        $key = "ackcount:*";
        self::clearlistByKeys($key);
        $key = "pushJsonsurid:*";
        self::clearlistByKeys($key);
        $key = "pushJsonid:*";
        self::clearlistByKeys($key);

        $error_list_key = "error_list_key";
        Redis::del($error_list_key);

        $md = date("md");
        $tokenkey = "schoolwstoken{$md}";
        Redis::del($tokenkey);


        $key = "stuldsorderno:*";
        self::clearlistByKeys($key);
        //  devlog("delrobotlist over");

    }

    public static function clearlistByKeys($keys)
    {

        $list = Redis::keys($keys);

        if ($list) {


            foreach ($list as $key) {
                $swoftkey = trim($key, "swoft:");
                Redis::del($swoftkey);
                //   devlog("del $swoftkey");

            }
        }
    }

    public function datasync()
    {
        $school_id = getenv("school_id");
        $post["school_id"] = $school_id;
        $host = getenv("host");
        $url = "{$host}api/lsods/datasync";
        $rt = Base::curlpost($url, $post);

        if (isset($rt["code"]) && $rt["code"] == 0) {
            $model = $rt["data"]["model"];
            if ($model == "Student") {
                $studentinfo = $rt["data"]["info"];

                if ($studentinfo) {
                    $student_id = $studentinfo["id"];
                    $getStudentByIdkey = "getStudentById:{$student_id}";
                    Base::redisSetArr($getStudentByIdkey, $studentinfo, 3600 * 24);
                } else {
                    devlog("datasync Student");
                    devlog($studentinfo);
                }
            } elseif ($model == "Robot") {

                $nrobotinfo = $rt["data"]["info"];
                $imei = $nrobotinfo["imei"];

                $robotkey = "robotinfo:{$imei}";


                Base::toast("机器人数据库修改 刷新列表");


                $robotinfo = self::getRobotCoachinfoByImei($imei);

                $robotinfo = array_merge($robotinfo, $nrobotinfo);


                Base::redisSetArr($robotkey, $robotinfo);


                // self::getRobotCoachinfoByImei($imei);

                $robotlist = Base::getrobotlist();

                $rdata["code"] = 0;
                $rdata["msg"] = "";
                $rdata["data"]["cmd"] = "initrobotlist";
                $rdata["data"]["robotinfolist"] = $robotlist;
                $rtjson = json_encode($rdata);
                //
                $surveillancelistkey = "surveillancelist";
                $surveillancelist = Base::redisGetArr($surveillancelistkey);
                if ($surveillancelist) {
                    foreach ($surveillancelist as $surveillanceinfo) {
                        $surveillancefd = $surveillanceinfo["fd"];
                        //                        server()->push($surveillancefd, $rtjson);
                        Base::pushJson($rdata, $surveillancefd);
                    }
                }
            } elseif ($model == "deltoken") {
                $md = date("md");
                $tokenkey = "schoolwstoken{$md}";
                Redis::del($tokenkey);

                Base::gettoken();
            }
        }
    }

    public static function getRobotCoachinfoByImei($imei)
    {
        $robotkey = "robotinfo:{$imei}";
        $robotinfo = Base::redisGetArr($robotkey);

        Base::getrobotlist();

        if (!isset($robotinfo["imei"])) {
            $robotinfo = [];
        }
        if (!$robotinfo) {
            $host = getenv("host");
            $url = "{$host}api/lsods/getrobotinfobyimei";
            $post["imei"] = $imei;
            $rt = Base::curlpost($url, $post);
            if ($rt["code"] == 0) {
                $robotinfo = $rt["data"]["robotinfo"];

                devlog("getRobotCoachinfoByImei");
                devlog($robotinfo);
                $robotinfo["call_status"] = Events::ROBOT_FREE; //是否能呼叫
                $robotinfo["status"] = Events::ROBOT_OFFLINE; //是否 在线
                $robotinfo["student_name"] = "";
                $robotinfo["error_list"] = self::getErrorListByImei($imei);

                $robotinfo["errnum"] = 0;
                $robotinfo["nomc"] = 0;
                $robotinfo["backcolor"] = "green";

                $robotkey = "robotinfo:{$imei}";

                Base::redisSetArr($robotkey, $robotinfo);
            }
        }
        return $robotinfo;
    }


    public static function getErrorListByImei($robotimei)
    {

        $new3errcode = Base::redisGetArr('stuCarNewNumberErrorArr' . $robotimei);
        if (empty($new3errcode)) {
            $new3errcode = [];
        }

        $new3errcode = array_slice(array_unique($new3errcode), 0, 3);
        $wrongJudgeArr = self::getErrorList();

        $WrongJudge = [];
        foreach ($wrongJudgeArr as $key => $v) {
            $WrongJudge[$v['code']] = $v['point'];
        }
        $errorCodeArr = [];
        foreach ($new3errcode as $errid) {
            if (!$WrongJudge[$errid]) {
                continue;
            }

            if (!empty($errid)) {

                $code3 = str_pad(substr($errid, 0, 3), 8, "0", STR_PAD_RIGHT);
                $code5 = str_pad(substr($errid, 0, 5), 8, "0", STR_PAD_RIGHT);

                $err3 = isset($WrongJudge[$code3]) ? $WrongJudge[$code3] : "未知项目:{$code3}"; //项目

                $err5 = isset($WrongJudge[$code5]) ? $WrongJudge[$code5] : "未知阶段:{$code5}"; //阶段
                $err = isset($WrongJudge[$errid]) ? $WrongJudge[$errid] : "未知错误:{$errid}"; //错误

                $errorCodeArr[] = '[' . $err3 . '] 一> ' . $err5 . ' :                              ' . $err;
            }
        }


        return $errorCodeArr;
    }


    public static function getErrorList()
    {
        $error_list_key = "error_list_key";
        $WrongJudgeArr = Base::redisGetArr($error_list_key);

        if (!$WrongJudgeArr) {
            $host = getenv("host");
            $url = "{$host}api/lsods/geterrlist";
            $post = [];
            $rt = Base::curlpost($url, $post);
            if (!$rt) {
                return [];
            }

            if (!isset($rt["code"])) {
                devlog("getErrorList no code");
                devlog($rt);
                return [];
            }

            if ($rt["code"] == 0) {
                $WrongJudgeArr = $rt["data"]["list"];
                Base::redisSetArr($error_list_key, $WrongJudgeArr, 3600 * 24);
            }
        }
        return $WrongJudgeArr;
    }

    public static function testws($robotfd)
    {
        $rdata["code"] = 0;
        $rdata["msg"] = "";
        $rdata["data"]["cmd"] = "testws";

        Base::pushJson($rdata, $robotfd); //surcallin
    }

    public static function robotonline()
    {
        $robotheartbeatkey = "robotheartbeatimei:*";

        $robotheartbeatlist = Redis::keys($robotheartbeatkey);
        //  devlog("robotonline:");
        //  devlog($robotheartbeatlist);

        $robot_idarr = [];
        $sub3robot_idarr = [];
        if ($robotheartbeatlist) {

            foreach ($robotheartbeatlist as $v) {
                $robotheartbeat = trim($v, "swoft:");
                $fdarr = explode(":", $robotheartbeat);
                $imei = $fdarr[1];
                $deviceinfo = self::getRobotInfoByImei($imei);
                if ($deviceinfo) {
                    $car_number = $deviceinfo["car_number"];
                    $subject = $deviceinfo["subject"];
                    if ($subject == 2) {
                        $robot_id = $deviceinfo["robot_id"];
                        $robot_idarr[] = $robot_id;
                        //测试延迟
                        if (!isset($deviceinfo["fd"])) {

                            continue;
                        }
                        $robotfd = $deviceinfo["fd"];
                        //    devlog("testws_send:{$robotfd}:{$car_number}");

                        self::testws($robotfd);
                    } else {
                        $robot_id = $deviceinfo["robot_id"];
                        $sub3robot_idarr[] = $robot_id;
                    }
                }
            }
        }
        $school_id = getenv("school_id");
        if ($robot_idarr) {

            $post["school_id"] = $school_id;
            $post["robot_ids"] = implode(",", $robot_idarr);


            $host = getenv("host");
            $url = "{$host}api/lsods/robotonline";

            $res = Base::curlpost($url, $post);
        }
        // if ($sub3robot_idarr) {

        //     $post["school_id"] = $school_id;
        //     $post["robot_ids"] = implode(",", $sub3robot_idarr);


        //     $host = getenv("host");
        //     $url = "{$host}api/lsods/sub3robotonline";

        //     $res = Base::curlpost($url, $post);
        // }

        $robotlist = Base::getrobotlist();

        $surdata["code"] = 0;
        $surdata["msg"] = "";
        $surdata["data"]["cmd"] = "initrobotlist";
        $surdata["data"]["robotinfolist"] = $robotlist;
        $school_id = getenv("school_id");

        $surdata["data"]["schoolinfo"]["school_id"] = $school_id;

        //  devlog($surdata);
        Base::broadcastsur($surdata);
    }

    public static function getRobotInfoByImei($imei)
    {
        $robotkey = "robotinfo:{$imei}";
        $robotinfo = Base::redisGetArr($robotkey);

        return $robotinfo;
    }

    /**
     * 机器人数据上传
     */

    public function robotdata()
    {
        $rediskey = "RobotData";
        $v = Redis::rPop($rediskey);


        while ($v) {





            $host = getenv("host");

            $url = "{$host}robot/Learnt/uploadRobotOssData";
            $rt = Base::curlpostdata($url, $v);


            $v = Redis::rPop($rediskey);
        }
    }

    public function checkrobotheartbeat()
    {
        // devlog("checkrobotheartbeat ");

        $robotheartbeatkey = "robotheartbeatimei:*";
        $robotheartbeatlist = Redis::keys($robotheartbeatkey);

        //["robotheartbeatimei:","robotheartbeatimei:501bcd42eeaaca3470c02ca5dff2ac12127fa6d2"]
        //   devlog($robotheartbeatlist);
        if ($robotheartbeatlist) {
            $now = time();
            foreach ($robotheartbeatlist as $v) {
                //   $robotheartbeat = trim($v, "swoft:");
                $robotheartbeat = $v;
                $fdarr = explode(":", $robotheartbeat);
                if (count($fdarr) != 2) {
                    continue;
                }
                $imei = $fdarr[1];
                //   devlog("checkrobotheartbeat {$imei}");
                $lastime = Base::redisGet($robotheartbeat);
                if (($now - $lastime) > 180) {
                    //checkrobotheartbeat robotheartbeatimei 掉线

                    //   devlog("checkrobotheartbeat {$imei} 掉线");

                    //掉线


                    //      devlog("checkrobotheartbeat   {$imei}");

                    $deviceinfo = self::getRobotInfoByImei($imei);
                    $toastmsg = "未知车辆 掉线";
                    if ($deviceinfo) {
                        //  devlog($deviceinfo);
                        // if (isset($deviceinfo["fd"])) {
                        //     devlog("deviceinfo no fd:");
                        //     devlog($deviceinfo);
                        //     $robotfd = $deviceinfo["fd"];
                        // } else {

                        //     $robotfd = "no fd";
                        // }

                        // $robotfd = $deviceinfo["fd"];
                        $car_number = $deviceinfo["car_number"];
                        $toastmsg = "{$car_number} 掉线";
                        Base::toast($toastmsg);
                        //  devlog("{$car_number} 掉线{$robotfd}");
                    }


                    self::remdevice($imei);

                    Redis::del($robotheartbeat);
                }
            }
        }

        // devlog("checkrobotheartbeat over");
    }

    public static function remdevice($imei)
    {


        $deviceinfo = self::getRobotInfoByImei($imei);
        devlog("remdevice:{$imei}" . json_encode($deviceinfo, JSON_UNESCAPED_UNICODE));


        if ($deviceinfo) {


            $surdata["code"] = 0;
            $surdata["msg"] = "";
            $surdata["data"]["cmd"] = "robotstatus";
            $surdata["data"]["status"] = 0;
            $surdata["data"]["imei"] = $imei;
            $surdata["data"]["robot_id"] = $deviceinfo["robot_id"];

            $surdata["data"]["car_number"] = $deviceinfo["car_number"];

            //    devlog($surdata);
            Base::broadcastsur($surdata);


            //机器人下线修改状态
            self::changeRobotStatus(self::ROBOT_OFFLINE, $imei);
        }
    }

    public static function changeRobotStatus($status, $imei)
    {

        $robotkey = "robotinfo:{$imei}";
        $robotinfo = Base::redisGetArr($robotkey);
        $robotinfo["status"] = $status;
        Base::redisSetArr($robotkey, $robotinfo);
    }

    public static function getRobot($imei)
    {

        $host = getenv("host");
        $url = "{$host}api/lsods/getrobotinfobyimei";
        $post["imei"] = $imei;
        $rt = Base::curlpost($url, $post);
        if ($rt["code"] == 0) {
            $robotinfo = $rt["data"]["robotinfo"];
            return $robotinfo;
        }
    }


    public function studytime()
    {

        $md = date("md");

        $loginkey = "userloginbyimei:{$md}:*";
        $userloginlist = Redis::keys($loginkey);
        if ($userloginlist) {
            $now = time();
            $list = [];
            foreach ($userloginlist as $v) {
                $userloginkey = trim($v, "swoft:");
                $imeiarr = explode(":", $userloginkey);
                $imei = $imeiarr[2];
                $time = Base::redisGet($userloginkey);
                $studytime = $now - $time;
                if ($studytime > 0 && $studytime < 3600 * 24) {
                    $min = floor($studytime / 60);
                    $list[] = [
                        "imei" => $imei,
                        "studytime" => $min
                    ];
                }
            }
            $rdata["code"] = 0;
            $rdata["msg"] = "";
            $rdata["data"]["cmd"] = "synctimelist";
            $rdata["data"]["timelist"] = $list;
            $surveillancelistkey = "surveillancelist";
            $surveillancelist = Base::redisGetArr($surveillancelistkey);
            if ($surveillancelist) {
                foreach ($surveillancelist as $surveillanceinfo) {
                    $surveillancefd = $surveillanceinfo["fd"];
                    Base::pushJson($rdata, $surveillancefd);
                }
            }
        }
    }


    public function test()
    {

        $rdata["code"] = 0;
        $rdata["msg"] = "戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩戴口罩";
        $rdata["data"]["cmd"] = "test";

        Base::broadcastsur($rdata);
    }

    public function datainit()
    {

        self::getErrorList();


        Base::getrobotlist();
    }
}
